package impl 

import  (
	"context"
	"github.com/google/uuid"

	"gitee.com/ChangPaoZhe/devops/apps/cmdb"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
	cmdbimpl  "gitee.com/ChangPaoZhe/devops/apps/cmdb/impl"
	commandimpl "gitee.com/ChangPaoZhe/devops/apps/command/impl"
	"gitee.com/ChangPaoZhe/devops/apps/cron"
	"time"
	"fmt"
	"gitee.com/ChangPaoZhe/devops/apps/command"
	"gitee.com/ChangPaoZhe/devops/config"
)

func NewDefaultCrontabCommand()  *cron.CrontabCommand {
	return  &cron.CrontabCommand{
	}
}
func NewDefaultAddFuncParamsRequest() *cron.AddFuncParamsRequest {
	return &cron.AddFuncParamsRequest{
	}
}

func DefaultRandom()  string  {
	randomUUID, err := uuid.NewRandom()
	if err != nil {
		panic(err)
	}
	return   randomUUID.String()
}
func  (c *ImplCron) CrontabHealth()  {
	collection:=c.MongoDb.Database(cmdb.App_Name).Collection("register")
	ctx:=context.Background()
	filter:=bson.M{}
	cursor,err:=collection.Find(ctx, filter)
	if err !=nil  {
		c.logger.Error().Msg(err.Error())
		return 
	}
	var resources   []*cmdb.Resource
	err=cursor.All(ctx,&resources)
	if err != nil {
		c.logger.Error().Msg(err.Error())
		return 
	}
	for _,resource:=range resources {
		c.logger.Info().Msg(fmt.Sprintf("-------%s\n",resource.String()))
		opts := options.FindOne().SetSort(bson.M{"upload_at": -1})
		filter:=bson.M{"resource._id": resource.Id}
		var  res  cmdb.HealthSave
		collection=c.MongoDb.Database(cmdb.App_Name).Collection("health")
		if err:=collection.FindOne(ctx,filter,opts).Decode(&res);err!=nil {
			c.logger.Error().Msg(err.Error())
			continue
		}
		c.logger.Info().Msg(fmt.Sprintf("health 查询资源:%s",res.String()))
		collection=c.MongoDb.Database(cron.App_Name).Collection("resource_status")
		filter=bson.M{"$and":[]bson.M{bson.M{"resource.region":resource.Region},bson.M{"resource.ipaddress": resource.Ipaddress}}}
		resource_status:=cmdbimpl.NewDefaultResourceStatus(resource)
		if  (time.Now().Unix()-res.UploadAt)<900 {
			resource_status.ResourceStatus=cmdb.Resource_Status_OnLine
		}else {
			resource_status.ResourceStatus=cmdb.Resource_Status_OffLine
		}
		var   resource_data  cmdb.ResourceStatus
		err:=collection.FindOne(ctx, filter).Decode(&resource_data)
		if err!=nil {
			msg:=fmt.Sprintf("查询resource_status 数据错误%s\n", err.Error())
			c.logger.Info().Msg(msg)
			resource_status.UploadAt=time.Now().Unix()
			_,err:=collection.InsertOne(ctx,resource_status)
			if err!=nil  {
				msg:=fmt.Sprintf("初始插入resource_status 错误%s\n", err.Error())
				c.logger.Error().Msg(msg)
			}
			continue
		}
		filter=bson.M{"_id": resource_data.Id}
		update:=bson.M{"$set": bson.M{"resource_status": resource_status.ResourceStatus,"upload_at": time.Now().Unix()}}
		_,err=collection.UpdateMany(ctx,filter,update)
		if err != nil {
			msg:=fmt.Sprintf("更新resource_status 错误%s\n", err.Error())
			c.logger.Error().Msg(msg)
			continue
		}else {
			msg:=fmt.Sprintf("更新resource_status: %s 成功", resource_status)
			c.logger.Info().Msg(msg)
		}
	}
}

// 构建 
func  (c  *ImplCron)AddFunc(ctx  context.Context ,req  *cron.AddFuncParamsRequest) (*cron.AddFuncParamsResponse ,error){
	resoueces,err:=c.Cmdb.Search(ctx, &cmdb.SearchRequest{
		Id: req.ResourcesId,
	})
	if err != nil {
		msg:=fmt.Errorf("资源查询失败")
		c.logger.Error().Msg(msg.Error())
		return  	 nil,msg 
	}
	collection:=c.MongoDb.Database(cron.App_Name).Collection("crontab")
	filter:=bson.M{"_id": req.MetadataId}
	metadata:=NewDefaultCrontabCommand()
	err=collection.FindOne(ctx, filter).Decode(metadata)
	if err!=nil {
		msg:=fmt.Errorf("查询crontab失败")
		c.logger.Error().Msg(msg.Error())
		return  	 nil,msg 
	}
	spec:=fmt.Sprintf("%s %s %s %s %s",metadata.CrontabMetadata.Min,metadata.CrontabMetadata.Hour,metadata.CrontabMetadata.Day,metadata.CrontabMetadata.Month,metadata.CrontabMetadata.Week)
	collection=c.MongoDb.Database(command.App_Name).Collection("params")
	filter=bson.M{"_id": req.InputParamsId}
	input_params:=commandimpl.NewDefaultInput_Params()
	err=collection.FindOne(ctx, filter).Decode(input_params)
	if err!=nil {
		msg:=fmt.Errorf("查询params失败")
		c.logger.Error().Msg(msg.Error())
		return  	nil,err
	}
	collection=c.MongoDb.Database(cron.App_Name).Collection("crontab_exec")
	for _,reource:=range  resoueces.Values {
		comandinput:=commandimpl.NewDefaultCommandInput()
		comandinput.Id=DefaultRandom()
		comandinput.InputParams=input_params
		comandinput.Resource=reource
		comandinput.CmdType=command.Cmd_Type_crontab
		comandinput.CrontabMetadata=metadata
		task:=func(){
			_,err:=c.Command.Exec(context.Background(), comandinput)
			if err!=nil {
				msg:=fmt.Sprintf("执行失败:%s",err.Error())
				c.logger.Error().Msg(msg)
			}
		}
		config.C.Crontab.AddFunc(spec, task)
		_,err=collection.InsertOne(ctx, comandinput)
		if err != nil {
			msg:=fmt.Errorf("数据插入失败:%s",err.Error())
			c.logger.Info().Msg(msg.Error())
			return nil, msg
		}
		c.logger.Info().Msg(fmt.Sprintf("spec:%s,input_params:%s",spec,input_params))
	}
	
	return  &cron.AddFuncParamsResponse{Response: fmt.Sprintf("resouces: %s\n,spec:%s\n,input_params:%s\n", req.ResourcesId,req.MetadataId,req.InputParamsId)},err
}


func(c  *ImplCron) InsertCront(ctx context.Context, req *cron.CrontabCommand) (*cron.CrontabCommand, error){
	collection:=c.MongoDb.Database(cron.App_Name).Collection("crontab")
	req.CreateAt=time.Now().Unix()
	req.Status=cron.Cron_Status_CRON_DISABLE
	req.Id=DefaultRandom()
	_,err:=collection.InsertOne(ctx,req)
	if  err != nil {
		msg:=fmt.Errorf("数据插入失败%s",err.Error())
		c.logger.Error().Msg(msg.Error())
		return nil, msg
	}
	c.logger.Info().Msg(req.String())
	return req,nil 
}
